#include "esp_log.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "string.h"
#include "driver/gpio.h"

#include "BSP.h"



#define I2C2                                        0
#define I2C3                                        1


#define  I2C2_SCL_PIN                               GPIO_NUM_3                           
#define  I2C2_SCL_LOW							    gpio_set_level(I2C2_SCL_PIN, 0)	
#define  I2C2_SCL_HIGHT						        gpio_set_level(I2C2_SCL_PIN, 1)

#define  I2C2_SDA_PIN                               GPIO_NUM_2                           
#define  I2C2_SDA_LOW							    gpio_set_level(I2C2_SDA_PIN, 0)
#define  I2C2_SDA_HIGHT						        gpio_set_level(I2C2_SDA_PIN, 1)
#define  I2C2_SDA_READ						        gpio_get_level(I2C2_SDA_PIN)


#define  I2C3_SCL_PIN                               GPIO_NUM_1                           
#define  I2C3_SCL_LOW							    gpio_set_level(I2C3_SCL_PIN, 0)	
#define  I2C3_SCL_HIGHT						        gpio_set_level(I2C3_SCL_PIN, 1)

#define  I2C3_SDA_PIN                               GPIO_NUM_0                           
#define  I2C3_SDA_LOW							    gpio_set_level(I2C3_SDA_PIN, 0)
#define  I2C3_SDA_HIGHT						        gpio_set_level(I2C3_SDA_PIN, 1)
#define  I2C3_SDA_READ						        gpio_get_level(I2C3_SDA_PIN)


static volatile  uint8_t DeviceType = 0;



/*	系统参数	*/
extern SystemParameter SysParam;
/*	系统状态	*/
extern SystemState SysState;




/**
* @brief  I2C的延时函数，延时xUS
* @param  us：延时时间
* @retval None
*/
static void I2C_Delay_1us( uint32_t us )
{
    uint32_t  Delay = us * 160;

	do
	{
		__asm__ __volatile__("nop");
	}
	while (Delay --);
}




/**
* @brief 主机产生起始信号
* @param  I2C_Port: 0--I2C2 1--I2C3
* @retval None
*/
static void I2C_Start( uint8_t I2C_Port )
{
    if( I2C_Port == I2C2 )
    {
        I2C2_SDA_HIGHT;
        I2C2_SCL_HIGHT;
        I2C_Delay_1us(5);

        I2C2_SDA_LOW;
        I2C_Delay_1us(5);

        I2C2_SCL_LOW;

    }
    else
    {
        I2C3_SDA_HIGHT;
        I2C3_SCL_HIGHT;
        I2C_Delay_1us(5);

        I2C3_SDA_LOW;
        I2C_Delay_1us(5);

        I2C3_SCL_LOW;
    }
}



/**
* @brief  主机产生停止信号
* @param  I2C_Port: 0--I2C2 1--I2C3
* @retval
*/
static void I2C_Stop( uint8_t I2C_Port )
{
    if( I2C_Port == I2C2 )
    {
        I2C_Delay_1us(5);
	
        I2C2_SDA_LOW;
        I2C2_SCL_HIGHT;
        
        I2C_Delay_1us(5);
        
        I2C2_SDA_HIGHT;
        I2C_Delay_1us(5);
    }
    else
    {
        I2C_Delay_1us(5);
	
        I2C3_SDA_LOW;
        I2C3_SCL_HIGHT;
        
        I2C_Delay_1us(5);
        
        I2C3_SDA_HIGHT;
        I2C_Delay_1us(5);
    }
}




/**
* @brief  主机发送应答信号
* @param  I2C_Port: 0--I2C2 1--I2C3
* @retval None
*/
static void I2C_SendACK( uint8_t I2C_Port )
{
    if( I2C_Port == I2C2 )
    {
        I2C2_SCL_LOW;
        I2C2_SDA_LOW;
        I2C_Delay_1us(5);

        I2C2_SCL_HIGHT;
        I2C_Delay_1us(5);

        I2C2_SCL_LOW;
    }
    else
    {
        I2C3_SCL_LOW;
        I2C3_SDA_LOW;
        I2C_Delay_1us(5);

        I2C3_SCL_HIGHT;
        I2C_Delay_1us(5);

        I2C3_SCL_LOW;
    }
}



/**
* @brief  主机发送非应答信号
* @param  I2C_Port: 0--I2C2 1--I2C3
* @retval None
*/
static void I2C_SendNACK( uint8_t I2C_Port )
{
    if( I2C_Port == I2C2 )
    {
        I2C2_SCL_LOW;
        I2C2_SDA_HIGHT;
        I2C_Delay_1us(5);

        I2C2_SCL_HIGHT;
        I2C_Delay_1us(5);

        I2C2_SCL_LOW;
    }
    else
    {
        I2C3_SCL_LOW;
        I2C3_SDA_HIGHT;
        I2C_Delay_1us(5);

        I2C3_SCL_HIGHT;
        I2C_Delay_1us(5);

	    I2C3_SCL_LOW;
    }
	
}


/**
* @brief  检查是否接收到应答信号
* @param  I2C_Port: 0--I2C2 1--I2C3
* @retval 1--成功		0--失败
*/
static unsigned char I2C_Check_ACK( uint8_t I2C_Port )
{
	uint8_t i;
	
    if( I2C_Port == I2C2 )
    {
        I2C2_SCL_LOW;
        I2C2_SDA_HIGHT;
        I2C_Delay_1us(5);
        
        I2C2_SCL_HIGHT;
        I2C_Delay_1us(5);
        
        if( I2C2_SDA_READ == 0 )
        {
            I2C2_SCL_LOW;
            return 1;
        }

        I2C2_SCL_LOW;
        return 0;
    }
    else 
    {
        I2C3_SCL_LOW;
        I2C3_SDA_HIGHT;
        I2C_Delay_1us(5);
        
        I2C3_SCL_HIGHT;
        I2C_Delay_1us(5);
        
        if( I2C3_SDA_READ == 0 )
        {
            I2C3_SCL_LOW;
            return 1;
        }

        I2C3_SCL_LOW;
        return 0;
    }
}



/**
* @brief I2C发送一个字节
* @param I2C_Port: 0--I2C2 1--I2C3
* @param byte: 发送的数据
* @retval None
*/
static void I2C_SendByte( uint8_t I2C_Port, uint8_t byte )
{
	uint8_t i, temp;

	temp = byte;

    if( I2C_Port == I2C2 )
    {
        for( i=0; i<8; i++ )
        {
            I2C2_SCL_LOW;
            
            if( (temp & 0x80) == 0x80 )
            {
                I2C2_SDA_HIGHT;
            }
            else I2C2_SDA_LOW;

            temp = temp << 1;

            I2C_Delay_1us(5);
            
            I2C2_SCL_HIGHT;
            
            I2C_Delay_1us(5);
        }
        
        I2C2_SCL_LOW;
    }
    else
    {
        for( i=0; i<8; i++ )
        {
            I2C3_SCL_LOW;
            
            if( (temp & 0x80) == 0x80 )
            {
                I2C3_SDA_HIGHT;
            }
            else I2C3_SDA_LOW;

            temp = temp << 1;

            I2C_Delay_1us(5);
            
            I2C3_SCL_HIGHT;
            
            I2C_Delay_1us(5);
        }
        
        I2C3_SCL_LOW;
    }
}




/**
* @brief I2C接收一个字节
* @param  I2C_Port: 0--I2C2 1--I2C3
* @retval 返回接收到的数据
*/
static unsigned char I2C_ReciveByte( uint8_t I2C_Port )
{
	uint8_t i, temp = 0;

    if( I2C_Port == I2C2 )
    {
        for( i=0; i<8; i++ )
        {
            temp <<= 1;
            
            I2C2_SCL_LOW;
            I2C_Delay_1us(5);

            I2C2_SCL_HIGHT;
            I2C_Delay_1us(5);
            
            if( I2C2_SDA_READ == 1 )
            {
                temp = temp | 0x01;
            }
        }
        
        I2C2_SCL_LOW;
    }
    else
    {
        for( i=0; i<8; i++ )
        {
            temp <<= 1;
            
            I2C2_SCL_LOW;
            I2C_Delay_1us(5);

            I2C2_SCL_HIGHT;
            I2C_Delay_1us(5);
            
            if( I2C2_SDA_READ == 1 )
            {
                temp = temp | 0x01;
            }
        }
        
        I2C2_SCL_LOW;
    }

	return temp;
}




/**
  * @brief  数码管显示数字
  * @param  led_select：0--第一块数码管 1--第二块数码管
  * @param  bit：0--千位
  *              1--百位
  *              2--十位
  *              3--个位
  * @param  num：显示数字
  *              数字：0--9, 10--15(0X0A--0X0F)
								 字符：'-'
								 字符：'N'
  *              关闭显示：OXFF
  * @param  decimal_point：0--不显示小数点  1--显示小数点
  * @retval 0--失败     1--成功
  */
uint8_t DigtalDisplay_Num( uint8_t led_select, uint8_t bit,  uint8_t num, uint8_t decimal_point )
{
    uint8_t temp = 0;

    if( led_select > 1 ) return 0;
	if( bit > 3 ) return 0;
    if( decimal_point > 1 ) return 0;
	if( (num != 0xff && num != '-' && num != 'N') && num > 15 )  return 0;
	
	I2C_Start( led_select );

	I2C_SendByte( led_select, 0x48 );
	if( I2C_Check_ACK( led_select ) == 0 ) 
	{
		I2C_Stop( led_select );
		return 0;
	}

	I2C_SendByte( led_select, 0x01 );
	if( I2C_Check_ACK( led_select ) == 0 ) 
	{
		I2C_Stop( led_select );
		return 0;
	}

	I2C_Stop( led_select );


	I2C_Start( led_select );

	I2C_SendByte( led_select, 0x68 + bit * 2 );
	if( I2C_Check_ACK( led_select ) == 0 ) 
	{
		I2C_Stop( led_select );
		return 0;
	}

	switch( num )
	{
		case 0:
		{
            temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X3F | temp) );
		}
		break;
		
		case 1:
		{
            temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X06 | temp) );
		}
		break;
		
		case 2:
		{
            temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X5B | temp)  );
		}
		break;
		
		case 3:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X4F | temp)  );
		}
		break;
		
		case 4:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X66 | temp)  );
		}
		break;
		
		case 5:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X6D | temp)  );
		}
		break;
		
		case 6:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X7D | temp)  );
		}
		break;
		
		case 7:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X07 | temp)  );
		}
		break;
		
		case 8:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X7F | temp)  );
		}
		break;
		
		case 9:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X6F | temp)  );
		}
		break;
		
		case 10:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X77 | temp)  );
		}
		break;
		
		case 11:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X7C | temp)  );
		}
		break;
		
		case 12:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X39 | temp)  );
		}
		break;
		
		case 13:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X5E | temp)  );
		}
		break;
		
		case 14:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X79 | temp)  );
		}
		break;
		
		case 15:
		{
			temp = decimal_point << 7;
			I2C_SendByte( led_select, (0X71 | temp)  );
		}
		break;
		
		case '-':
		{
			I2C_SendByte( led_select, 0X40 );
		}
		break;
		
		case 'N':
		{
			I2C_SendByte( led_select, 0X37 );
		}
		break;
		
		case 0xff:
		{
			I2C_SendByte( led_select, 0x00 );
		}
		break;
	}
	
	if( I2C_Check_ACK( led_select ) == 0 ) 
	{
		I2C_Stop( led_select );
		return 0;
	}
	
	I2C_Stop( led_select );
	return 1;
}





/**
  * @brief  数码管显示测试
  * @param  None
  * @retval None
  */
// static void DigtalDisplay_Test( void )
// {
// 	uint8_t i;
	
// 	for( i=0; i<16; i++ )
// 	{
// 		DigtalDisplay_Num( 0, 0, i, 1 );
// 		DigtalDisplay_Num( 0, 1, i, 1 );
// 		DigtalDisplay_Num( 0, 2, i, 1 );
//         DigtalDisplay_Num( 0, 3, i, 1 );

//         DigtalDisplay_Num( 1, 0, i, 1 );
// 		DigtalDisplay_Num( 1, 1, i, 1 );
// 		DigtalDisplay_Num( 1, 2, i, 1 );
//         DigtalDisplay_Num( 1, 3, i, 1 );
		
// 		 vTaskDelay( 1000 / portTICK_PERIOD_MS );
// 	}
	
//     DigtalDisplay_Num( 0, 0, 0xff, 0 );
//     DigtalDisplay_Num( 0, 1, 0xff, 0 );
//     DigtalDisplay_Num( 0, 2, 0xff, 0 );
//     DigtalDisplay_Num( 0, 3, 0xff, 0 );

//     DigtalDisplay_Num( 1, 0, 0xff, 0 );
//     DigtalDisplay_Num( 1, 1, 0xff, 0 );
//     DigtalDisplay_Num( 1, 2, 0xff, 0 );
//     DigtalDisplay_Num( 1, 3, 0xff, 0 );
// }



/**
  * @brief  初始化数码管显示
  * @param  None
  * @retval None
  */
void  DigtalDisplay_Init( void )
{
    //zero-initialize the config structure.
    gpio_config_t io_conf = {};

    //disable interrupt
    io_conf.intr_type = GPIO_INTR_DISABLE;
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT_OD;
    //bit mask of the pins that you want to set
    io_conf.pin_bit_mask = (1ULL<<I2C2_SCL_PIN) ;
    //disable pull-down mode
    io_conf.pull_down_en = 0;
    //enable pull-up mode
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
    //configure GPIO with the given settings
    gpio_config(&io_conf);

    //set as output and input with open-drain mode
    io_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD;
    //bit mask of the pins that you want to set
    io_conf.pin_bit_mask = (1ULL<<I2C2_SDA_PIN) ;
    //configure GPIO with the given settings
    gpio_config(&io_conf);

    //set as output and input with open-drain mode
    io_conf.mode = GPIO_MODE_OUTPUT_OD;
    //bit mask of the pins that you want to set
    io_conf.pin_bit_mask = (1ULL<<I2C3_SCL_PIN) ;
    //configure GPIO with the given settings
    gpio_config(&io_conf);

    //set as output and input with open-drain mode
    io_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD;
    //bit mask of the pins that you want to set
    io_conf.pin_bit_mask = (1ULL<<I2C3_SDA_PIN) ;
    //configure GPIO with the given settings
    gpio_config(&io_conf);


    I2C2_SCL_LOW;
    I2C2_SDA_LOW;

    vTaskDelay( 20 / portTICK_PERIOD_MS );

	/*  关闭数码管显示  */
    DigtalDisplay_Num( 0, 0, 0xff, 0 );
    DigtalDisplay_Num( 0, 1, 0xff, 0 );
    DigtalDisplay_Num( 0, 2, 0xff, 0 );
    DigtalDisplay_Num( 0, 3, 0xff, 0 );

    DigtalDisplay_Num( 1, 0, 0xff, 0 );
    DigtalDisplay_Num( 1, 1, 0xff, 0 );
    DigtalDisplay_Num( 1, 2, 0xff, 0 );
    DigtalDisplay_Num( 1, 3, 0xff, 0 );

    vTaskDelay( 1000 / portTICK_PERIOD_MS );

	// DigtalDisplay_Test( );		//数码管显示测试

    DeviceType = SysParam.WorkParam.DeviceType;
}





/**
* @brief 显示温度、湿度
* @param None
* @retval None
*/
void DisplayTempHumidity( void )
{
    static uint16_t time_cnt = 0;
    uint8_t fault = 0;
    float temp = 0, rh = 0;
    uint16_t value = 0;

    time_cnt++;
    if( time_cnt >= 50 )    //每隔500ms更新一次数据
    {
        time_cnt = 0;

        if( DeviceType == AtpsSa)
        {
            fault = SysState.AtpsSaParam.SensorFault;
            temp = SysState.AtpsSaParam.TDB;
            rh = SysState.AtpsSaParam.RH;
        }
        else if( DeviceType == AtpsOa)
        {
            fault = SysState.AtpsOaParam.SensorFault;
            temp = SysState.AtpsOaParam.TDB;
            rh = SysState.AtpsOaParam.RH;
        }
        else if( DeviceType == AtpsRa)
        {
            fault = SysState.AtpsRaParam.SensorFault;
            temp = SysState.AtpsRaParam.TDB;
            rh = SysState.AtpsRaParam.RH;
        }
        else if( DeviceType == AtpsMa)
        {
            fault = SysState.AtpsMaParam.SensorFault;
            temp = SysState.AtpsMaParam.TDB;
            rh = SysState.AtpsMaParam.RH;
        }
        else  if( DeviceType == AtpsExa)
        {
            fault = SysState.AtpsExaParam.SensorFault;
            temp = SysState.AtpsExaParam.TDB;
            rh = SysState.AtpsExaParam.RH;
        }
        else  if( DeviceType == AtpsRooma)
        {
            fault = SysState.AtpsRoomaParam.SensorFault;
            temp = SysState.AtpsRoomaParam.TDB;
            rh = SysState.AtpsRoomaParam.RH;
        }
        else  if( DeviceType == AtpsCoola)
        {
            fault = SysState.AtpsCoolaParam.SensorFault;
            temp = SysState.AtpsCoolaParam.TDB;
            rh = SysState.AtpsCoolaParam.RH;
        }
        else  if( DeviceType == AtpsHeata)
        {
            fault = SysState.AtpsHeataParam.SensorFault;
            temp = SysState.AtpsHeataParam.TDB;
            rh = SysState.AtpsHeataParam.RH;
        }
        else  if( DeviceType == AtpsHuma)
        {
            fault = SysState.AtpsHumaParam.SensorFault;
            temp = SysState.AtpsHumaParam.TDB;
            rh = SysState.AtpsHumaParam.RH;
        }
        else  if( DeviceType == AtpsPre)
        {
            fault = SysState.AtpsPreParam.SensorFault;
            temp = SysState.AtpsPreParam.TDB;
            rh = SysState.AtpsPreParam.RH;
        }
        else  if( DeviceType == AtpsRot)
        {
            fault = SysState.AtpsRotParam.SensorFault;
            temp = SysState.AtpsRotParam.TDB;
            rh = SysState.AtpsRotParam.RH;
        }


        if( fault != NoFault )
        {
            /*  故障，温度显示-99  */
            DigtalDisplay_Num( 0, 0, 0xff, 0 );
            DigtalDisplay_Num( 0, 1, '-', 0 );
            DigtalDisplay_Num( 0, 2, 9, 0 );
            DigtalDisplay_Num( 0, 3, 9, 0 );

            /*  故障，湿度显示-99  */
            DigtalDisplay_Num( 1, 0, 0xff, 0 );
            DigtalDisplay_Num( 1, 1, '-', 0 );
            DigtalDisplay_Num( 1, 2, 9, 0 );
            DigtalDisplay_Num( 1, 3, 9, 0 );
        }
        else 
        {
            /*  更新温度  */
            if( temp > -100 && temp < 1000 )
            {
                if( temp > -100 && temp <= -10 )
                {
                    value =( 0 - temp )  * 10.0;

                    DigtalDisplay_Num( 0, 0, '-', 0 );
                    DigtalDisplay_Num( 0, 1, (value / 100), 0 );
                    DigtalDisplay_Num( 0, 2,(value / 10 % 10), 1 );
                    DigtalDisplay_Num( 0, 3, (value % 10), 0 );
                }
                else if( temp > -10 && temp < 0 )
                {
                    value = ( 0 - temp ) * 100.0;

                    DigtalDisplay_Num( 0, 0, '-', 0 );
                    DigtalDisplay_Num( 0, 1, (value / 100), 1 );
                    DigtalDisplay_Num( 0, 2,(value / 10 % 10), 0 );
                    DigtalDisplay_Num( 0, 3, (value % 10), 0 );
                }
                else if( temp >= 0 && temp < 10 )
                {
                    value = temp * 100.0;

                    DigtalDisplay_Num( 0, 0, 0xff, 0 );
                    DigtalDisplay_Num( 0, 1, (value / 100), 1 );
                    DigtalDisplay_Num( 0, 2,(value / 10 % 10), 0 );
                    DigtalDisplay_Num( 0, 3, (value % 10), 0 );
                }
                else if( temp >= 10 && temp < 100 )
                {
                     value = temp * 100.0;

                    DigtalDisplay_Num( 0, 0, (value / 1000), 0 );
                    DigtalDisplay_Num( 0, 1, (value / 100 % 10), 1 );
                    DigtalDisplay_Num( 0, 2,(value / 10 % 10), 0 );
                    DigtalDisplay_Num( 0, 3, (value % 10), 0 );
                }
                else 
                {
                    value = temp * 10.0;

                    DigtalDisplay_Num( 0, 0, (value / 1000), 0 );
                    DigtalDisplay_Num( 0, 1, (value / 100 % 10), 0 );
                    DigtalDisplay_Num( 0, 2,(value / 10 % 10), 1 );
                    DigtalDisplay_Num( 0, 3, (value % 10), 0 );
                }
            }


            /*  更新湿度  */
            if( rh >=0 && rh <= 100 )
            {
                if( rh >= 0 && rh < 10 )
                {
                    value = rh * 100.0;

                    DigtalDisplay_Num( 1, 0, 0xff, 0 );
                    DigtalDisplay_Num( 1, 1, (value / 100), 1 );
                    DigtalDisplay_Num( 1, 2,(value / 10 % 10), 0 );
                    DigtalDisplay_Num( 1, 3, (value % 10), 0 );
                }
                else if( rh >= 10 && rh < 100 )
                {
                    value = rh * 100.0;

                    DigtalDisplay_Num( 1, 0, (value / 1000), 0 );
                    DigtalDisplay_Num( 1, 1, (value / 100 % 10), 1 );
                    DigtalDisplay_Num( 1, 2,(value / 10 % 10), 0 );
                    DigtalDisplay_Num( 1, 3, (value % 10), 0 );
                }
                else 
                {
                    value = rh * 10.0;

                    DigtalDisplay_Num( 1, 0, (value / 1000), 0 );
                    DigtalDisplay_Num( 1, 1, (value / 100 % 10), 0 );
                    DigtalDisplay_Num( 1, 2,(value / 10 % 10), 1 );
                    DigtalDisplay_Num( 1, 3, (value % 10), 0 );
                }
            }

        }
    }
}
















